package net.wanglu.www.zzz.service.se.nsubj;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Pattern;

import net.wanglu.www.zzz.service._Service;
import net.wanglu.www.zzz.service.se.expl._ExplTuple;
import edu.stanford.nlp.trees.EnglishGrammaticalRelations;
import edu.stanford.nlp.trees.GrammaticalRelation;
import edu.stanford.nlp.trees.Tree;
import edu.stanford.nlp.trees.TreeGraphNode;
import edu.stanford.nlp.trees.TypedDependency;
import edu.stanford.nlp.trees.tregex.TregexMatcher;
import edu.stanford.nlp.trees.tregex.TregexPattern;

public class ExplNSubjExtracter extends _Service {

	@Override
	public Object service(Object... objects) throws Exception {
		// TODO Auto-generated method stub
		HashMap<?, ?> preprocessData = (HashMap<?, ?>) objects[0];
		final TypedDependency expl = (TypedDependency) objects[1];
		final List<?> ExplTupleList = (List<?>) objects[2];
		
		TreeGraphNode explGov = expl.gov();
		Tree root = (Tree) preprocessData.get("root");
		Collection<?> tdl = (Collection<?>) preprocessData.get("tdl");
		
		TypedDependency nsubj = null;
		TypedDependency aux = null;
		TypedDependency cop = null;
		TypedDependency xcomp = null;
		TypedDependency acomp = null;
		TypedDependency dobj = null;
		for( Object obj : tdl) {
			TypedDependency TD = (TypedDependency) obj;
			GrammaticalRelation reln = TD.reln();
			if ( reln.equals(EnglishGrammaticalRelations.NOMINAL_SUBJECT) || reln.equals(EnglishGrammaticalRelations.NOMINAL_PASSIVE_SUBJECT)) {
				if ( TD.gov().toString().equals(explGov.toString())) {
					nsubj = TD;
				}
			} else if ( reln.equals(EnglishGrammaticalRelations.AUX_MODIFIER) || reln.equals(EnglishGrammaticalRelations.AUX_PASSIVE_MODIFIER)) {
				if ( TD.gov().toString().equals(explGov.toString())) {
					if ( aux == null ||  root.depth(TD.dep()) < root.depth(aux.dep())) {
						aux = TD;
					}
				}
			} else if ( reln.equals(EnglishGrammaticalRelations.COPULA)) {
				if ( TD.gov().toString().equals(explGov.toString())) {
					cop = TD;
				}
			} else if ( reln.equals(EnglishGrammaticalRelations.XCLAUSAL_COMPLEMENT)) {
				if ( TD.gov().toString().equals(explGov.toString())) {
					xcomp = TD;
				}
			} else if ( reln.equals(EnglishGrammaticalRelations.ADJECTIVAL_COMPLEMENT)) {
				if ( TD.gov().toString().equals(explGov.toString())) {
					acomp = TD;
				}
			} else if ( reln.equals(EnglishGrammaticalRelations.DIRECT_OBJECT)) {
				if ( TD.gov().toString().equals(explGov.toString())) {
					dobj = TD;
				}
			}
		}

		TreeGraphNode closestAux = (aux == null ? null : aux.dep());
		TreeGraphNode copula = (cop == null ? null : cop.dep());
		TreeGraphNode subj = null;
		TreeGraphNode verb = null;
		
		if ( aux != null && cop != null) {//#助动词+be作谓语动词
			subj = explGov;
			verb = closestAux;
		} else if ( aux != null && dobj != null) {//#含存在意义的及物动词的被动式谓语动词
			subj = dobj.dep();
			verb = explGov;				
		} else if ( aux != null && xcomp != null) {//#被动式谓语动词
			subj = xcomp.dep();
			verb = explGov;			
		} else if ( xcomp != null) {//#半助动词+be作谓语动词
			subj = xcomp.dep();
			verb = explGov;
		} else if ( dobj != null) {//#不及物动词作谓语动词
			subj = dobj.dep();
			verb = explGov;
		} else if ( acomp != null) {
			subj = acomp.dep();
			verb = explGov;
		} else if ( nsubj != null) {
			subj = nsubj.dep();
			verb = explGov;
		} else {
			subj = expl.dep();
			verb = expl.gov();
		}

		
		/*
		 * 谓语祖先
		 */
		Tree verbAncestor = null;

		sb.clear();
		sb.append("/\\bV[A-Z]+\\b/");
		sb.append(">");
		sb.append("/\\bS\\b|\\bSBAR\\b|\\bSBARQ\\b|\\bSINV\\b|\\bSQ\\b/");
		sb.append("<<");
		sb.append("(");
		sb.append("/").append(Pattern.quote(verb.label().tag())).append("/").append("<");
		sb.append("/").append(Pattern.quote(verb.label().word())).append("/");
		sb.append(")");
		TregexPattern pattern = TregexPattern.compile(sb.toString());
		TregexMatcher matcher = pattern.matcher(root);
		/*
		 * 寻找离它最近的祖先
		 */
		Tree tmp = null;
		while ( matcher.find()) {
			Tree node = matcher.getMatch();
			if ( tmp == null || node.depth() < tmp.depth()) {
				tmp = node;
			}
		}
		
		if ( tmp != null) {
			verbAncestor = tmp;
		} else {
			verbAncestor = verb;
		}
	
		/*
		 * 主语祖先
		 */
		Tree subjectAncestor = null;

		sb.clear();
		sb.append("/\\bNP\\b/");
		sb.append("<").append("(");
		sb.append("/").append(Pattern.quote(subj.label().tag())).append("/");
		sb.append("<");
		sb.append("/").append(Pattern.quote(subj.label().word())).append("/");
		sb.append(")");
		pattern = TregexPattern.compile(sb.toString());
		matcher = pattern.matcher(root);
		if ( matcher.find()) {
			subjectAncestor = matcher.getMatch();
		}
/*		if ("NP".equals(subjectAncestor.parent(root).value())) {
			subjectAncestor = subjectAncestor.parent(root);
		}*/
		final TreeGraphNode faux = closestAux;
		final TreeGraphNode fcop = copula;
		final TreeGraphNode fsubj = subj;
		final Tree fsubjectAncestor = subjectAncestor;
		final TreeGraphNode fverb = verb;
		final Tree fverbAncestor = verbAncestor;
		final String frelation = expl.reln().getShortName();
		
		return new _NSubjTuple() {
			{
				this.setAux(faux);
				this.setCop(fcop);
				this.setSubj(fsubj);
				this.setSubjectAncestor(fsubjectAncestor);
				this.setVerb(fverb);
				this.setVerbAncestor(fverbAncestor);
				this.setRelation(frelation);
			}
			@Override
			public Object customize() throws Exception {
				// TODO Auto-generated method stub
				for( Object obj : ExplTupleList) {
					_ExplTuple et = (_ExplTuple) obj;
					if ( et.getExplGov().toString().equals(expl.gov().toString())) return et;
				}
				return null;
			}
		};
	}
}
